#pragma once

#include <string>
#include <vector>
#include <jsoncpp/json/json.h>

namespace WordMemory
{
    struct Example
    {
        int id;
        std::string example;
        std::string translation;

        Example(int id = 0, const std::string& example = "", const std::string& translation = "")
            : id(id), example(example), translation(translation)
        {
        }

        Json::Value to_json() const
        {
            Json::Value json;
            json["id"] = id;
            json["example"] = example;
            json["translation"] = translation;
            return json;
        }

        void from_json(const Json::Value& json)
        {
            id = json["id"].asInt();
            example = json["example"].asString();
            translation = json["translation"].asString();
        }
    };

    struct Word
    {
        int id;
        std::string word;
        std::string meaning;
        std::vector<Example> examples;
        std::vector<std::string> mnemonics;

        Word(int id = 0,
            const std::string& word = "",
            const std::string& meaning = "",
            const std::vector<Example>& examples = {},
            const std::vector<std::string>& mnemonics = {})
            : id(id), word(word), meaning(meaning), examples(examples), mnemonics(mnemonics)
        {
        }

        Json::Value to_json() const
        {
            Json::Value json;
            json["id"] = id;
            json["word"] = word;
            json["meaning"] = meaning;

            Json::Value examples_array(Json::arrayValue);
            for (const auto& item : examples) {
                examples_array.append(item.to_json());
            }
            json["examples"] = examples_array;

            Json::Value mnemonics_array(Json::arrayValue);
            for (const auto& item : mnemonics) {
                mnemonics_array.append(item);
            }
            json["mnemonics"] = mnemonics_array;

            return json;
        }

        void from_json(const Json::Value& json)
        {
            id = json["id"].asInt();
            word = json["word"].asString();
            meaning = json["meaning"].asString();

            examples.clear();
            const Json::Value& examples_json_array = json["examples"];
            if (examples_json_array.isArray()) {
                for (const auto& example_json : examples_json_array) {
                    Example ex;
                    ex.from_json(example_json);
                    examples.push_back(ex);
                }
            }

            mnemonics.clear();
            const Json::Value& mnemonics_json_array = json["mnemonics"];
            if (mnemonics_json_array.isArray()) {
                for (const auto& mnemonic_json_item : mnemonics_json_array) {
                    if (mnemonic_json_item.isString()) {
                        mnemonics.push_back(mnemonic_json_item.asString());
                    }
                }
            }
        }
    };

    struct WordWithFavoriteStatus
    {
        int id;
        std::string word;
        std::string meaning;
        std::vector<Example> examples;
        std::vector<std::string> mnemonics;
        bool is_favorite;

        WordWithFavoriteStatus(const Word& word, bool favorite)
            : id(word.id), word(word.word), meaning(word.meaning),
              examples(word.examples), mnemonics(word.mnemonics),
              is_favorite(favorite)
        {}

        Json::Value to_json() const
        {
            Json::Value json;
            json["id"] = id;
            json["word"] = word;
            json["meaning"] = meaning;

            for (const auto& example : examples)
                json["examples"].append(example.to_json());

            for (const auto& mnemonic : mnemonics)
                json["mnemonics"].append(mnemonic);

            json["is_favorite"] = is_favorite;

            return json;
        }

        void from_json(const Json::Value& json)
        {
            id = json["id"].asInt();
            word = json["word"].asString();
            meaning = json["meaning"].asString();
            is_favorite = json["is_favorite"].asBool();

            examples.clear();
            const Json::Value& examples_json_array = json["examples"];
            if (examples_json_array.isArray()) {
                for (const auto& example_json : examples_json_array) {
                    Example ex;
                    ex.from_json(example_json);
                    examples.push_back(ex);
                }
            }

            mnemonics.clear();
            const Json::Value& mnemonics_json_array = json["mnemonics"];
            if (mnemonics_json_array.isArray()) {
                for (const auto& mnemonic_json_item : mnemonics_json_array) {
                    if (mnemonic_json_item.isString()) {
                        mnemonics.push_back(mnemonic_json_item.asString());
                    }
                }
            }
        }
    };

}